package producer_consumer_my;

// Fig. 23.18: SynchronizedBuffer.java
// Synchronizing access to shared data using Object 
// methods wait and notify.
public class SynchronizedBuffer implements Buffer
{
   private int SIZE;
   private int [] buffer; // shared by producer and consumer threads
   private int current =0;// whether the buffer is occupied

   SynchronizedBuffer(int n)
   {
       SIZE=n;
       buffer=new int [n];
   }
   // place value into buffer
   public synchronized void set( int value ) throws InterruptedException
   {
      // while there are no empty locations, place thread in waiting state
      while ( current>SIZE )
      {
         // output thread information and buffer information, then wait
         System.out.println( "Producer tries to write." );
         displayState( "Buffer full. Producer waits." );
         wait();
      } // end while
      buffer[current++] = value; // set new buffer value
      // indicate producer cannot store another value
      // until consumer retrieves current buffer value
     // occupied = true;
        
      displayState( "Producer writes "   );
      
      notifyAll(); // tell waiting thread(s) to enter runnable state
   } // end method set; releases lock on SynchronizedBuffer 
    
   // return value from buffer
   public synchronized int get() throws InterruptedException
   {
      // while no data to read, place thread in waiting state
      while ( current==0 )
      {
         // output thread information and buffer information, then wait
         System.out.println( "Consumer tries to read." );
         displayState( "Buffer empty. Consumer waits." );
         wait();
      } // end while

      // indicate that producer can store another value 
      // because consumer just retrieved buffer value
     // occupied = false;

      displayState( "Consumer reads "   );
      
      notifyAll(); // tell waiting thread(s) to enter runnable state

      return buffer[current--];
   } // end method get; releases lock on SynchronizedBuffer 
    
   // display current operation and buffer state
   public void displayState( String operation )
   {
      System.out.printf( "%-40s\t\t%d\t%d\n", operation,current,buffer[current] );
   } // end method displayState
} // end class SynchronizedBuffer


